<?php
// +----------------------------------------------------------------------
// | 磁盘服务层
// +----------------------------------------------------------------------
// | 主要服务于磁盘路径配置
// +----------------------------------------------------------------------
// | 错误编码头 211xxx
// +----------------------------------------------------------------------
namespace common\service;


use common\exception\LogicException;
use common\model\CheckListModel;
use common\model\ProjectCheckListModel;
use common\model\ProjectModel;
use common\model\ProjectStepReviewWorkflowRelationModel;
use common\model\ReviewWorkflowModel;
use common\model\StepReviewWorkflowRelationModel;
use common\model\StepWorkflowModel;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;

class ReviewWorkflowService
{
    private $reviewWorkflowModel;

    private $stepReviewWorkflowRelationModel;

    // 单例工具
    use SingletonTrait;

    /**
     * ReviewWorkflowService constructor.
     */
    public function __construct()
    {
        $this->reviewWorkflowModel = model(ReviewWorkflowModel::class);
        $this->stepReviewWorkflowRelationModel = model(StepReviewWorkflowRelationModel::class);
    }

    /**
     * @param $type
     * @return DelayOrderTaskReviewWorkflowService|void
     */
    public function getObject($type)
    {
        switch ($type) {
            case 'DelayOrderTask':
                return DelayOrderTaskReviewWorkflowService::getInstance();
                break;
        }
    }

    /**
     * 软删除
     * @param $param
     * @return array
     * @throws \Exception
     */
    public function delete($param)
    {
        $reviewWorkflowModel = model(ReviewWorkflowModel::class);
        // 获取当前模块删除主键
        $masterIdData = $reviewWorkflowModel->field('id')->where($param["param"]['filter'])->select();

        if (!empty($masterIdData)) {
            $masterIds = join(',', array_column($masterIdData, 'id'));
            $resData = $reviewWorkflowModel->save(['is_deleted' => "yes"], ['where' => ['id' => ["IN", $masterIds]]]);

            if (!$resData) {
                // 通用删除失败错误码 003
                throw new LogicException($reviewWorkflowModel->getError(), ErrorCode::REVIEW_WORKFLOW_DELETE_FAILURE);
            } else {
                // 返回成功数据
                return ['ids' => $masterIds];
            }
        } else {
            throw new LogicException('Delete item does not exist.', ErrorCode::DELETE_ITEM_NOT_EXIST);
        }
    }

    /**
     * 获得一个审核数据
     * @param $fields
     * @param $filter
     * @return mixed
     */
    public function getWorkflow($fields, $filter)
    {
        return $this->reviewWorkflowModel
            ->where($filter)
            ->field($fields)
            ->find();
    }

    /**
     * 解析config字段
     * @param $config
     * @return array
     */
    public static function parseConfig(array $config)
    {
        $promoter = $config['promoter'] ?? null;
        $reviewer = $config['reviewer'] ?? [];
        $cc = $config['cc'] ?? [];
        return [$promoter, $reviewer, $cc];
    }

    /**
     * 查询审核流信息
     * @param array $filter
     * @param string $fields
     * @return array|false|mixed|string
     */
    public function selectStepReviewWorkFlowByStepReviewRelation(array $filter, $fields = 'rw.*')
    {
        return model(StepReviewWorkflowRelationModel::class)->alias('srw')
            ->join('review_workflow AS rw ON srw.review_workflow_id = rw.id')
            ->where($filter)
            ->field($fields)
            ->select();

    }

    /**
     * @param int $stepId
     * @return array|null
     */
    public function getStepReviewWorkflowParsed(int $stepId)
    {
        $config = $this->stepReviewWorkflowRelationModel
            ->join('review_workflow on review_workflow.id = step_review_workflow_relation.review_workflow_id')
            ->where(['step_review_workflow_relation.step_id' => $stepId])
            ->field('review_workflow.config')->getField('config');
        if (empty($config)) {
            return null;
        }
        $config = json_decode($config, true);
        return self::parseConfig($config['nodes']);
    }

    /**
     * 获得解析好的工序流信息
     * @param array $reviewFilter
     * @return array
     */
    public function getParsedWorkflow(array $reviewFilter)
    {
        $nodesData = $this->getWorkflow(["id,name,description,config"], $reviewFilter);
        if (empty($nodesData)) {
            throw new LogicException("can`t found a active review workflow", ErrorCode::ACTIVE_REVIEW_WORKFLOW_CONFIG_NOT_FOUND);
        }
        //解析节点
        $nodesData['config'] = json_decode($nodesData['config'] ?? '{}', true);
        $res = self::parseConfig($nodesData['config']['nodes']);
        array_unshift($res, $nodesData);
        return $res;
    }

    /**
     * 查询审核流信息
     * @param $param
     * @return array
     * @throws Exception
     */
    public function selectReviewWorkflow($param)
    {
        $commonService = CommonService::instance('review_workflow');
        $data = $commonService->select($param, 'review_workflow');
        $roleCodes = [];
        array_map(function ($item) use (&$roleCodes) {
            foreach ($item['config']['nodes']['reviewer'] as $reviewNode) {
                $roleCodes[$reviewNode['role']] = $reviewNode['role'];
            }
            return $item;
        }, $data['rows']);
        $roleNameMap = [];
        if (count($roleCodes)) {
            $roleFilter = ['param' => [
                'filter' => [
                    'role.code' => ['-in', array_values($roleCodes)]
                ],
            ]];
            $roleList = teamones_request('teamones-im', 'role/select', $roleFilter)['data']['rows'];
            $roleNameMap = array_column($roleList, 'name', 'code');
        }
        foreach ($data['rows'] as &$row) {
            foreach ($row['config']['nodes']['reviewer'] as &$reviewNode) {
                $roleCodes[$reviewNode['role']] = $reviewNode['role'];
                $reviewNode['role_cname'] = $roleNameMap[$reviewNode['role']] ?? 'unknown';
            }
        }
        return $data;
    }

    /**
     * 获得任务审核流配置信息
     * @param int $taskId
     * @param int $projectId
     * @param int $stepWorkflowId
     * @param int $stepId
     * @return array|mixed|string
     */
    public function getTaskReviewWorkflowRelationConfig(int $taskId, int $projectId, int $stepWorkflowId, int $stepId)
    {
        $attrStr = TaskService::getInstance()->getTaskStandardDocAttrStrById($taskId);
        $stepWorkflow = model(StepWorkflowModel::class)
            ->field('id,source_id')
            ->find($stepWorkflowId);
        if (($stepWorkflow['source_id'] ?? 0) > 0) {
            $stepWorkflowId = $stepWorkflow['source_id'];
        }
        $projectReviewWorkflowRelationFilter = [
            'project_id' => $projectId,
            'step_workflow_id' => $stepWorkflowId,
            'step_id' => $stepId,
            'attr_str' => $attrStr,
        ];
        return $this->getProjectStepReviewWorkflow($projectReviewWorkflowRelationFilter);
    }

    /**
     * 获取项目对应的工序的审核流
     * @param $projectReviewWorkflowRelationFilter
     * @return mixed
     */
    public function getProjectStepReviewWorkflow($projectReviewWorkflowRelationFilter)
    {
        $projectReviewWorkflowRelation = model(ProjectStepReviewWorkflowRelationModel::class)->where($projectReviewWorkflowRelationFilter)->find();
        if (empty($projectReviewWorkflowRelation) || $projectReviewWorkflowRelation['review_workflow_id'] == 0) {
            throw new LogicException("task did not config review workflow", ErrorCode::REVIEW_WORKFLOW_CONFIG_NOT_FOUND);
        }
        return CommonService::getFormatAttrData(model(ProjectStepReviewWorkflowRelationModel::class), $projectReviewWorkflowRelation);
    }

    /**
     * 获得任务的审核检查节点
     * @param int $taskId
     * @param int $projectId
     * @param int $stepWorkflowId
     * @param int $stepId
     * @return array
     */
    public function getTaskCheckListConfig(int $taskId, int $projectId, int $stepWorkflowId, int $stepId)
    {
        $taskService = TaskService::getInstance();
        $attrStr = $taskService->getTaskStandardDocAttrStrById($taskId);
        $projectTemplateId = model(ProjectModel::class)->field('project_template_id')->find($projectId);
        $projectTemplateId = $projectTemplateId['project_template_id'];
        $checkListFilter = [
            'project_template_id' => $projectTemplateId,
            'step_workflow_id' => $stepWorkflowId,
            'step_id' => $stepId,
            'attr_str' => $attrStr,
        ];
        $checkListList = model(CheckListModel::class)->where($checkListFilter)->select();
        if (empty($checkListList)) {
            return [];
        }

        $checkListIdList = array_column($checkListList, 'id');
        $projectCheckListFilter = [
            'project_id' => $projectId,
            'check_list_id' => ['IN', $checkListIdList]
        ];
        $projectCheckListList = model(ProjectCheckListModel::class)->where($projectCheckListFilter)->select();
        $projectCheckListList = array_column($projectCheckListList, 'review_role_config', 'check_list_id');

        return array_map(function ($item) use (&$projectCheckListList) {
            $projectReviewRoleConfig = $projectCheckListList[$item['id']] ?? $item['review_role_config'];
            $item['review_role_config'] = array_values(array_filter(explode(',', $projectReviewRoleConfig), function ($i) {
                return !empty($i);
            }));
            $item['check_role_nodes'] = [];
            return $item;
        }, $checkListList);
    }

    /**
     * 获得影子任务的审核流配置
     * @return string
     */
    public function getShadowTaskReviewConfig()
    {
        return OptionsService::getInstance()->getOptionsConfigItemData('order_review_config', 'task_party_a_review_workflow_id');
    }
}
